package cn.itcast.service.impl;

import cn.itcast.aspect.LogOperation;
import cn.itcast.mapper.DeptMapper;
import cn.itcast.mapper.EmpExprMapper;
import cn.itcast.mapper.EmpLogMapper;
import cn.itcast.mapper.EmpMapper;
import cn.itcast.pojo.*;
import cn.itcast.service.EmpExprService;
import cn.itcast.service.EmpService;
import cn.itcast.utils.JwtUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.time.LocalDate;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;

@Service
@Slf4j
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private EmpExprMapper empExprMapper;
    @Autowired
    private EmpLogMapper empLogMapper;
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpExprService empExprService;


    /**
     * 批量删除员工信息
     *
     * @param ids
     * @return
     */

    @Override
    @Transactional
    public Result removeEmpsByIds(List<Integer> ids) {
        //删除员工和经历信息
        //removeByIds(ids);
        removeBatchByIds(ids);
        empExprService.remove(new LambdaQueryWrapper<EmpExpr>().in(EmpExpr::getEmpId, ids));
        return Result.success("批量删除成功");
    }

    /**
     * 修改员工信息
     * 1.更新员工信息
     * 2.删除所有的工作经历
     * 3.插入新的工作经历
     *
     * @param emp
     * @return
     */
    @Override
    public Result updateEmp(Emp emp) {
        emp.setUpdateTime(LocalDateTime.now());
        LambdaUpdateWrapper<Emp> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(Emp::getId, emp.getId());
        update(emp, updateWrapper);
        //删除员工所有的工作经历
//        LambdaQueryWrapper<EmpExpr> queryWrapper = Wrappers.lambdaQuery();
//        queryWrapper.eq(EmpExpr::getEmpId, emp.getId());
//        empExprMapper.delete(queryWrapper);
        // 根据id批量删除员工的工作经历信息
        empExprService.remove(new LambdaQueryWrapper<EmpExpr>().eq(EmpExpr::getEmpId, emp.getId()));
        List<EmpExpr> exprList = emp.getExprList();
        if (exprList != null) {
            exprList.forEach(expr -> {
                expr.setEmpId(emp.getId());
            });
            empExprService.saveBatch(exprList);
        }

        return Result.success("员工信息更新成功");
    }


    /**
     * 根据id查询员工信息
     *
     * @param id
     * @return
     */
    @Override
    public Result getEmpById(Integer id) {
        Emp byId = getById(id);
        //根据员工id去查看有没有对应的工作经历
        LambdaQueryWrapper<EmpExpr> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(EmpExpr::getEmpId, id);
        List<EmpExpr> empExprs = empExprService.list(queryWrapper);
        byId.setExprList(empExprs);
       /* Dept dept = deptMapper.selectById(byId.getDeptId());
        if (dept != null) {
            byId.setDeptName(dept.getName());
        }*/
        return Result.success("查询成功", byId);
    }


    /**
     * 添加员工信息
     *
     * @param emp
     * @return
     */
    @Override
    @Transactional  //涉及到多表的更改
    public Result savemp(Emp emp) {
        //1.补全其他字段
        emp.setUpdateTime(LocalDateTime.now());
        emp.setCreateTime(LocalDateTime.now());
        Dept dept = deptMapper.selectById(emp.getDeptId());
        emp.setDeptName(dept.getName());
        boolean save = save(emp);
        List<EmpExpr> exprList = emp.getExprList();
        if (exprList != null) {
            exprList.forEach(expr -> {
                expr.setEmpId(emp.getId());
            });
            //empExprMapper.insert(exprList);  //这个是根据mapper层的方法去插入
            empExprService.saveBatch(exprList); //这个是根据service层的方法,进行插入
        }
        return Result.success("员工添加成功", save);
    }


    /**
     * 分页查询  使用mybatisPlus编写业务逻辑
     *
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public Result select(String name, Integer gender, LocalDate begin, LocalDate end, Integer page, Integer pageSize) {

        Page<Emp> empPage = Page.of(page, pageSize);
        // 根据最后修改时间倒序排序
        empPage.addOrder(OrderItem.desc("update_time"));

        //构建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like((name != null && !name.isEmpty()), Emp::getName, name)
                .eq((gender != null), Emp::getGender, gender)
                .between((begin != null && end != null), Emp::getEntryDate, begin, end);

        // 调用Service层查询分页数据
        empPage = page(empPage, queryWrapper);
        //获取总条数和数据
        List<Emp> records = empPage.getRecords();

        long total = empPage.getTotal();
        //1.这是使用集合遍历的方式来实现员工所属部门的添加
//        //定义集合存放员工所属的部门id
//        List<Integer> list = new ArrayList<>();
//        records.forEach(emp -> {
//            list.add(emp.getDeptId());
//        });
//
//        List<Dept> depts = deptMapper.selectByIds(list);
//        //遍历部门集合,封装部门名称
//        depts.forEach(dept -> {
//            records.forEach(emp -> {
//                if (dept.getId().equals(emp.getDeptId())) {
//                    emp.setDeptName(dept.getName());
//                }
//            });
//        });
        //2.使用stream流实现员工所属部门的添加
        List<Integer> list = records.stream().map(Emp::getDeptId).toList();
        if (!list.isEmpty()) {
            //调用dept的mapper层
            List<Dept> depts = deptMapper.selectByIds(list);
            records.forEach(emp -> {
                depts.stream().filter(dept -> dept.getId().equals(emp.getDeptId()))
                        .findFirst().ifPresent(dept -> emp.setDeptName(dept.getName()));
            });
            return Result.success("分页查询成功", new PageResult<Emp>(total, records));
        }


        return Result.success("分页查询成功", new PageResult<Emp>());

        /*//1.告诉分页助手,我要查询第几页,每页显示多少条数据
        PageHelper.startPage(page, pageSize);
        //2.调用mapper层
        List<Emp> emps = empMapper.search(name, gender, begin, end);
        //3.向下转型
        Page<Emp> p = (Page<Emp>) emps;
        long total = p.getTotal();
        List<Emp> list = p.getResult();

        return Result.success("分页查询成功", new PageResult(total, list));*/

    }


    @Override
    public Result select(Integer page, Integer pageSize) {


        /*//1.告诉分页助手,我要查询第几页,每页显示多少条数据
        PageHelper.startPage(page, pageSize);

        //2.分页助手会使用代理帮我们补上了limit后面的语句,并且帮我们查询了总个数,还修改了返回值
        //将返回值变成了List类型的子类Page,里面封装了很多数据,我们需要解析数据,拿到我们想要的
        //具体做法是需要向下转型,因为是多态写法,不能直接使用子类特有的功能
        //转型后,调用getResult方法拿到数据,getTotal方法拿到总个数
        List<Emp> emps = empMapper.page();

       *//* Page<Emp> p = (Page<Emp>) emps;
        long total = p.getTotal();
        List<Emp> list = p.getResult();*//*

        //使用new Page 的方式,把emps传进去
        PageInfo<Emp> page1 = new PageInfo<>(emps);
        //拿到list(员工数据)和total(数量)
        List<Emp> list = page1.getList();
        long total = page1.getTotal();


        return emps != null ? Result.success("分页查询成功", new PageResult(total, list)) : Result.error("查询失败");*/
        return null;
    }

    @Override
    @Transactional
    @LogOperation
    public Result addEmp(Emp emp) {
        /*Integer rows;
        try {
            //1.补全其他字段
            emp.setPassword("123456");
            emp.setUpdateTime(LocalDateTime.now());
            emp.setCreateTime(LocalDateTime.now());

            //2.调用mapper层
            rows = empMapper.addEmp(emp);
            //3.需要把工作履历相关的数据,添加到工作经历表中
            //4.获取emp中的List集合(里面放的就是工作履历)
            List<EmpExpr> exprList = emp.getExprList();
            //5.如果用户没有添加工作履历,那么exprList长度为0,就不需要添加工作履历,直接返回
            if (!exprList.isEmpty()) {
                exprList.forEach(empExpr -> empExpr.setEmpId(emp.getId()));
                empExprMapper.insertData(exprList);
            }

            return rows != 0 ? Result.success("插入成功") : Result.error("插入失败");
        } finally {
            //5.将日志信息插入到日志表中,并且需要再Mapper层的insertLog方法需要声明一个@Transactional(propagation = REQUIRES_NEW)注解,是一个新事物
            //empLogMapper.insertLog(new Op(null, LocalDateTime.now(), emp.getName() + "添加成功,他的手机号是:" + emp.getPhone()));
        }*/
        return null;

    }

    @Override
    public Result selectAll() {
        List<Emp> emps = empMapper.selectList(null);
        return emps != null ? Result.success("查询成功", emps) : Result.error("查询失败");
    }

    @Override
    @LogOperation
    public Result deleteByIds(List<Integer> ids) {
        /*//1.因为员工中还有履历外键,所以需要先删除员工表,再删除员工履历表
        Integer rows = empMapper.deleteByIds(ids);

        empExprMapper.deleteByIds(ids);
        return rows != 0 ? Result.success("删除成功") : Result.error("删除失败");*/
        return null;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result selectById(Integer id) {
        /*Emp emp = empMapper.selectById(id);
        List<EmpExpr> exprs = empExprMapper.selectById(id);
        //将查到的履历表数据添加到员工对象中
        emp.setExprList(exprs);
        这是自己写的,查询两次,没有联查
        */
       /* Emp emp = empMapper.selectId(id);
        return emp != null ? Result.success("查询成功", emp) : Result.error("查询失败");*/
        return null;
    }


    @Transactional(rollbackFor = Exception.class)
    @LogOperation
    public Result update1(Emp emp) {
        /*//1.设置更新时间
        emp.setUpdateTime(LocalDateTime.now());
        //2.更新员工表
        int row = empMapper.update(emp);
        //3.删除原来的老履历
        Integer id = emp.getId();
        ArrayList<Integer> list = new ArrayList<>();
        list.add(id);
        empExprMapper.deleteByIds(list);

        //4.把新的履历添加到数据库中
        List<EmpExpr> exprList = emp.getExprList();
        System.out.println("===========================");
        System.out.println(exprList);
        if (!exprList.isEmpty()) {
            exprList.forEach(e -> {
                e.setEmpId(id);
            });
            empExprMapper.insertData(exprList);
        }

        return row > 0 ? Result.success("修改成功") : Result.error("修改失败");*/
        return null;
    }

    @Override
    public Result login(Emp emp) {

        LoginInfo loginInfo = empMapper.searchUsernameAndPassword(emp);

        if (loginInfo != null) {
            //1.生成JWT令牌
            HashMap<String, Object> dataMap = new HashMap<>();
            dataMap.put("id", loginInfo.getId());
            dataMap.put("username", loginInfo.getUsername());

            String jwt = JwtUtils.generateJwt(dataMap);
            loginInfo.setToken(jwt);
            return Result.success("登录成功", loginInfo);
        }
        log.info("" + loginInfo);
        return Result.error("登录失败");
    }



/*    @Override
    public Result select(Integer page, Integer pageSize) {
        long total = empMapper.count();

        Integer start = (page - 1) * pageSize;

        List<Emp> emps = empMapper.page(start, pageSize);

        PageResult<Emp> pageResult = new PageResult<>(total, emps);

        return emps != null ? Result.success("分页查询成功", pageResult) : Result.error("查询失败");
    }*/
}
